package com.duoqin.syncassistant.viewmodel;

import android.app.Application;
import android.arch.lifecycle.LiveData;
import android.arch.lifecycle.MutableLiveData;
import android.os.Environment;
import android.support.annotation.NonNull;
import android.util.Log;
import android.widget.Toast;

import com.android.contacts.vcard.ExportProcessor;
import com.duoqin.common.data.remote.ApiClient;
import com.duoqin.syncassistant.R;
import com.duoqin.syncassistant.Utils;
import com.duoqin.syncassistant.data.BackupFileDownloadResponse;
import com.duoqin.syncassistant.data.remote.RemoteAddContactsApiInterface;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;

import okhttp3.ResponseBody;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;

public class VCardViewModel extends BaseViewModel {
    private static final String TAG = "duoqin_VCardViewModel";

    private static final String key = "duoqin001";

    private RemoteAddContactsApiInterface mApiInterface;
    private MutableLiveData<BackupFileDownloadResponse> mDownloadVCardResponse;

    public VCardViewModel(@NonNull Application application) {
        super(application);
        mApiInterface = ApiClient.getvCardClient().create(RemoteAddContactsApiInterface.class);
    }

    public LiveData<BackupFileDownloadResponse> vcardDownLoadResponse() {
        if (mDownloadVCardResponse == null) {
            mDownloadVCardResponse = new MutableLiveData<>();
        }
        return mDownloadVCardResponse;
    }

    public void downloadVCard(final String code) {
        Log.d(TAG, "downloadVCard code = " + code);
        if (code == null || code.length() != 6) return;

        final String timestamp = Utils.timestamp();
        final String auth = Utils.checksum_HmacSHA1(timestamp, key);
        final Call<ResponseBody> call = mApiInterface.downloadVCard(timestamp, auth, code);
        if (call != null) {
            call.enqueue(new Callback<ResponseBody>() {
                @Override
                public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
                    Log.d(TAG, "onResponse = " + response);
                    if (response != null && mDownloadVCardResponse != null) {
                        BackupFileDownloadResponse vCardDownloadResponse = new BackupFileDownloadResponse();
                        if (200 == response.code()) {
                            File file = new File(getApplication().getCacheDir(),
                                    ExportProcessor.VCARD_FILE_NAME);
                            try {
                                if (file.exists()) {
                                    file.delete();
                                }

                                byte[] vCardBytes = response.body().bytes();
                                String serverVCardMd5 = response.headers().get("md5");
                                String md5_computed = Utils.md5(vCardBytes);
                                if (serverVCardMd5 != null && md5_computed.matches(serverVCardMd5)) {
                                    FileOutputStream fos = new FileOutputStream(file);
                                    fos.write(vCardBytes);
                                    fos.flush();
                                    fos.close();
                                    Log.d(TAG, "vCard received = " + file.getAbsolutePath());
                                    vCardDownloadResponse.setCode(SERVER_RESULT_SUCCESS);
                                    vCardDownloadResponse.setPath(file.getAbsolutePath());
                                    // delete vCard file on server
                                    deleteVCard(timestamp, auth, code);
                                } else { // file not valid
                                    vCardDownloadResponse.setCode(SERVER_RESULT_ERROR_INVALID_HASH);
                                }
                            } catch (Exception e) {
                                vCardDownloadResponse.setCode(LOCAL_ERROR_DEFAULT);
                                if (file.exists()) {
                                    file.delete();
                                }
                                e.printStackTrace();
                            }
                            mDownloadVCardResponse.setValue(vCardDownloadResponse);
                        } else {
                            if (400 == response.code()) {
                                vCardDownloadResponse.setCode(SERVER_RESULT_ERROR_INVALID_CODE);
                            } else {
                                vCardDownloadResponse.setCode(SERVER_RESULT_ERROR_UNKNOWN);
                            }
                            mDownloadVCardResponse.setValue(vCardDownloadResponse);
                            String errorString = null;
                            try {
                                errorString = response.errorBody().string();
                            } catch (IOException e) {
                                e.printStackTrace();
                            }
                            Log.w(TAG, "error " + errorString);
                        }
                    }
                }

                @Override
                public void onFailure(Call<ResponseBody> call, Throwable t) {
                    Log.e(TAG, t.toString());
                    Toast.makeText(getApplication(), R.string.network_error_default,
                            Toast.LENGTH_SHORT).show();
                    if (mDownloadVCardResponse != null) {
                        mDownloadVCardResponse.setValue(null);
                    }
                }
            });
        }
    }

    private void deleteVCard(String timestamp, String auth, String code) {
        Log.d(TAG, "deleteVCard code = " + code);
        final Call<ResponseBody> call = mApiInterface.deleteVCard(timestamp, auth, code);
        if (call != null) {
            call.enqueue(new Callback<ResponseBody>() {
                @Override
                public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
                    Log.d(TAG, "onResponse = " + response);
                }

                @Override
                public void onFailure(Call<ResponseBody> call, Throwable t) {
                    Log.e(TAG, t.toString());
                }
            });
        }
    }
}
